#include "ASeq.h"
#include "ICounted.h" 
#include "EmptyList.h"
#include "Cons.h"

namespace clojure_lang {
ASeq::ASeq(void)
{
}


ASeq::~ASeq(void)
{
}


int ASeq::getHashCode()
{
	if (_hash == -1)
	{
		int h = 1;
                for(ISeq *s = seq(); s != NULL; s = s->next())
			h = 31 * h + (s->first() == NULL ? 0 : s->first()->getHashCode());
		_hash = h;

	}
	return _hash;

}

bool ASeq::equiv(CjObject *obj)
{
        if (obj->dynamicCast<Sequential>() == NULL)
		return false;
	//TODO RT.
        ISeq *ms = obj->dynamicCast<ISeq>();

        for (ISeq *s = seq(); s != NULL; )
	{
		//TODO: RT.

		ms = ms->next();
		s = s->next();
	}

	return ms == NULL;
}

IPersistentCollection *ASeq::cons(CjObject *obj)
{
        return new Cons(obj, this->dynamicCast<ISeq>());

}

int ASeq::count()
{
	int i = 1;
        for (ISeq *s = next(); s != NULL;)
        {
                if (dynamic_cast<ICounted *>(s))
                        return i + dynamic_cast<ICounted *>(s)->count();

		s = s->next();
		i++;
	}
	return i;
}

IPersistentCollection *ASeq::empty()
{
        return new EmptyList();
}

ISeq *ASeq::more()
{
        ISeq *s = next();
        if (s == NULL) {
                EmptyList *l = new EmptyList();
                return l->dynamicCast<ISeq>();
                    }
	return s;

}

ASeq::ASeq(IPersistentMap *meta) : CjObject(meta)
{


}

bool ASeq::equals(CjObject *obj)
{
    return equiv(obj);

}

ISeq *ASeq::seq()
{
    return this->dynamicCast<ASeq>();
}

}
